﻿using System.Collections.Generic;
using UnityEngine;

public class MsgDispatch
{
    private static MsgDispatch m_Inst;
    public static MsgDispatch Instance
    {
        get
        {
            if (null == m_Inst)
                m_Inst = new MsgDispatch();
            return m_Inst;
        }
    }

    public delegate void OnMessage(string msg, object data);

    struct MsgReceiver
    {
        public string m_MsgName;
        public OnMessage m_Func;
    }

    private Dictionary<string, List<OnMessage>> m_OnMsgListDict = new Dictionary<string, List<OnMessage>>();
    private Dictionary<object, HashSet<string>> m_TargetToMsgNames = new Dictionary<object, HashSet<string>>();

    public bool AddReceiver(string msgName, OnMessage func)
    {
        //Debug.Log($"AddReceiver: {func.Target.GetType().Name}");
        if (!m_OnMsgListDict.TryGetValue(msgName, out var list))
        {
            list = new List<OnMessage>();
            m_OnMsgListDict.Add(msgName, list);
        }

        if (!list.Contains(func))
        {
            list.Add(func);

            if (!m_TargetToMsgNames.TryGetValue(func.Target, out var msgNameList))
            {
                msgNameList = new HashSet<string>();
                m_TargetToMsgNames.Add(func.Target, msgNameList);
            }
            msgNameList.Add(msgName); //一个消息名可以注册多个委托
            return true;
        }
        else
        {
            Debug.Log($"AddReceiver: contains");
        }
        return false;
    }

    public bool RemoveReceiver(string msgName, OnMessage func)
    {
        if (m_OnMsgListDict.TryGetValue(msgName, out var list))
        {
            return list.Remove(func);
        }
        return false;
    }

    public bool RemoveReceivers(object target)
    {
        if (m_TargetToMsgNames.TryGetValue(target, out var msgNameList))
        {
            int removeNum = 0;
            foreach (var msgName in msgNameList)
            {
                if (m_OnMsgListDict.TryGetValue(msgName, out var list))
                {
                    for (int i = list.Count - 1; i >= 0; --i)
                    {
                        if (list[i].Target == target)
                        {
                            list.RemoveAt(i);
                            removeNum++;
                        }
                    }
                }
            }
            Debug.Log($"RemoveReceivers: ct:{removeNum}");
            return removeNum > 0;
        }
        
        return false;
    }

    public bool Dispatch(string msg, object data)
    {
        if (m_OnMsgListDict.TryGetValue(msg, out var list))
        {
            int lastIndex = list.Count - 1;
            for (int i = lastIndex; i >= 0; --i)
            {
                var func = list[i];
                func(msg, data);
            }
            return lastIndex >= 0;
        }
        return false;
    }

}
